﻿using UnityEngine;
using System.Collections.Generic;
using System;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using LitJson;

namespace FairyGUI.VFairyGUI
{
	public class FairyGUIWindowManager
    {
	   
    	#region 数据成员
        //配置文件名称
        private static string _windowInformation = "WindowInformation.json";
        //包管理器
        FairyGUIPackageManager _fairyGUIPackageManager=new FairyGUIPackageManager();
	    //显示窗体栈
    	Stack<FairyGUIBaseWindow> _showWindowStack = new Stack<FairyGUIBaseWindow>();
	    //窗体列表
    	private List<FairyGUIBaseWindow> _windowList=new List<FairyGUIBaseWindow>();

        private List<FairyGUIWindowInfo> _windowInfos;
        private static FairyGUIWindowManager _instance;
    	#endregion

        #region 属性
        
        /// <summary>
        /// 单例模式
        /// </summary>
        public static FairyGUIWindowManager instance
        {
	        get
	        {
		        if (_instance == null)
		        {
			        _instance = new FairyGUIWindowManager();
			        _instance.Init();
		        }
			        
		        return _instance;
	        }
        }

        #endregion

        #region 方法

        /// <summary>
        /// 加载配置文件，创建窗体类。
        /// </summary>
    	private void Init()
    	{
	        string bytePath = Application.streamingAssetsPath+"/" + _windowInformation;
	        if (File.Exists(bytePath))
	        {
		        using (FileStream fileStream=new FileStream(bytePath,FileMode.Open,FileAccess.Read,FileShare.Read))
		        {
			        using (StreamReader streamReader=new StreamReader(fileStream,Encoding.UTF8))
			        {
				        _windowInfos = JsonMapper.ToObject<List<FairyGUIWindowInfo>>(streamReader.ReadToEnd());
			        }
		        }
	        }
	        else
	        {
		        Debug.LogError("读取配置文件失败，请重新生成配置文件！");
		        return;
	        }
    		foreach (var item in _windowInfos)
    		{
			    if (item.fairyGuiWindowType == FairyGUIWindowTypes.Resource)
			    {
				    _fairyGUIPackageManager.AddPackage(item.packagePath,item.packageName);
			    }    
    		}
    	}
    
        /// <summary>
        /// 通过窗体枚举类型来得到对应窗体信息
        /// </summary>
        /// <param name="FairyGUIWindowName">窗体类型枚举</param>
        /// <returns></returns>
    	private FairyGUIBaseWindow GetFairyGUIBaseWindow(Type FairyGUIWindowType)
        {
    		foreach (var item in _windowList)
    		{
    			if (item.fairyGuiWindowInfo.windowName == FairyGUIWindowType.Name)
    				return item;
    		}
    		return null;
    	}

        private FairyGUIWindowInfo GetFairyGUIWindowInfo(Type FairyGUIWindowType)
        {
	        foreach (var item in _windowInfos)
	        {
		        if (item.windowName == FairyGUIWindowType.Name)
			        return item;
	        }
	        return null;
        }
    	
        /// <summary>
        /// 显示窗体
        /// </summary>
        /// <param name="FairyGUIWindowName">窗体类型枚举</param>
    	public void OpenWindow(Type fairyGUIWindowType)
    	{
	        FairyGUIBaseWindow bw;
    		if (_showWindowStack.Count > 0)
    		{
    			bw = _showWindowStack.Peek();
    			bw.OnPause();
    			bw.Hide();
                _fairyGUIPackageManager.UnloadAssets(bw.fairyGuiWindowInfo.packageName);
    		}
		    bw = GetFairyGUIBaseWindow(fairyGUIWindowType);
		    if (bw == null)
		    {
			    FairyGUIWindowInfo fairyGuiWindowInfo = GetFairyGUIWindowInfo(fairyGUIWindowType);
			    if (fairyGuiWindowInfo == null)
			    {
				    Debug.LogError("要开打的不是窗体，请检查OpenWindow函数的参数是否为FairyGUIBaseWindow的子类并且已在注册表注册！");
				    return;
			    }
			    if (fairyGuiWindowInfo.fairyGuiWindowType == FairyGUIWindowTypes.Window)
			    {
				    _fairyGUIPackageManager.AddPackage(fairyGuiWindowInfo.packagePath,fairyGuiWindowInfo.packageName);
				    _fairyGUIPackageManager.UnloadAssets(fairyGuiWindowInfo.packageName);
				    Assembly assembly=Assembly.LoadFrom(fairyGUIWindowType.Assembly.Location);
				    Type type = assembly.GetType(fairyGuiWindowInfo.windowName);
				    if (type == null)
				    {
					    Debug.LogError("导入的"+fairyGuiWindowInfo.packageName+"包，并没有为其创建对应脚本文件，请创建"+fairyGuiWindowInfo.windowName+"脚本并继承自FairyGUIBaseWindow。");
					    return;
				    }
				    object obj = type.Assembly.CreateInstance(type.Name);
				    bw = obj as FairyGUIBaseWindow;
				    bw.Copy(fairyGuiWindowInfo);
				    GComponent view = UIPackage.CreateObject(bw.fairyGuiWindowInfo.packageName, bw.fairyGuiWindowInfo.windowName).asCom;
				    bw.SetWindowView(view);
				    _windowList.Add(bw);
			    }
			    else
			    {
				    Debug.LogError("尝试创建资源包中的组件！资源包中的任何组件都无法被创建。");
				    return;
			    }
		    }
		    _fairyGUIPackageManager.ReloadAssets(bw.fairyGuiWindowInfo.packageName);
		    if (!bw.hasOpen)
		    {
			    _showWindowStack.Push(bw);
			    bw.hasOpen = true;
			    bw.OnBeforeOpen();
			    bw.OnOpen();
			    bw.Show();
		    }
		    else
		    {
			    bw.OnResume(); 
			    bw.Show();
		    }
    	}
    
        /// <summary>
        /// 暂时隐藏窗体
        /// </summary>
        /// <param name="FairyGUIWindowName">窗体类型枚举</param>
    	public void HideWindow(Type FairyGUIWindowType)
    	{
    		
	        FairyGUIBaseWindow bw = GetFairyGUIBaseWindow(FairyGUIWindowType);
	        if (bw == null)
	        {
		        Debug.LogError("要关闭的不是窗体，请检查HideWindow函数的参数是否为FairyGUIBaseWindow的子类并且已在注册表注册！");
		        return;
	        }
		    while(_showWindowStack.Count>0)
		    {
			    bw = _showWindowStack.Pop();
			    bw.OnPause();
			    bw.Hide();
			    _fairyGUIPackageManager.UnloadAssets(bw.fairyGuiWindowInfo.packageName);
			    if (bw.fairyGuiWindowInfo.windowName == FairyGUIWindowType.Name)
				    break;
		    }
		    if (_showWindowStack.Count >= 1)
		    {
			    bw = _showWindowStack.Peek();
			    _fairyGUIPackageManager.ReloadAssets(bw.fairyGuiWindowInfo.packageName);
			    bw.OnResume();
			    bw.Show();
		    }
    	}
		
        /// <summary>
        /// 销毁所有窗体
        /// </summary>
	    public void DestroyAllWindow()
	    {
		    while (_showWindowStack.Count > 0)
		    {
			    FairyGUIBaseWindow bw = _showWindowStack.Pop();
			    bw.OnBeforeClose();
			    bw.OnClose();
			    bw.Hide();
			    _fairyGUIPackageManager.UnloadAssets(bw.fairyGuiWindowInfo.packageName);
		    }

		    foreach (var VARIABLE in _windowList)
		    {
			    _fairyGUIPackageManager.RemovePackage(VARIABLE.fairyGuiWindowInfo.packageName);
		    }
	    }

        #endregion
        
    }
}

